package jzqb.controller.admin;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import haha.life.common.CutPageBean;
import haha.life.common.ExcelResolve;
import haha.life.common.MonitorTypeTool;
import haha.life.common.PermissionTypeTool;
import haha.life.normal.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jzqb.annotation.PermissionCheck.PermissionCheck;
import jzqb.annotation.loginlog.LoginLog;
import jzqb.bo.AdminUserInfoBo;
import jzqb.common.AdminResult;
import jzqb.common.Result;
import jzqb.po.AdminDepartmentPo;
import jzqb.po.AdminLoginPo;
import jzqb.po.AdminUserPo;
import jzqb.service.AdminDepartmentService;
import jzqb.service.AdminUserInfoService;
import jzqb.service.MonitorService;
import net.sf.json.JSONArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.server.PathParam;
import java.beans.IntrospectionException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

import static haha.life.normal.TokenUtils.checkTokenReturnID;

@RestController
@CrossOrigin
@RequestMapping("/adminUserInfo")
@Api(tags = "用户后台接口")
public class AdminUserInfoController {
    @Autowired
    private AdminUserInfoService adminuserinfoservice;

    @Autowired
    private AdminDepartmentService admindepartmentservice;

    @Value("${filePath.updUserExcelPath}")
    private String updUserExcelPath;

    @Autowired
    private ExcelResolve excelResolve;

    @Autowired
    private MonitorService monitorService;

    @LoginLog()
    @ApiOperation(value = "登录接口")
    @PostMapping("login")
    @ResponseBody
    public Result login(
            @RequestBody HashMap<String, String> map
    ) {
        String id = map.get("id");
        String pwd = map.get("pwd");
        Result res = adminuserinfoservice.login(id, pwd);
        return res;
    }


    @ApiOperation(value = "登出接口")
    @GetMapping("logout")
    public AdminResult logout(
            @PathParam("access_token") String access_token
    ) {
        System.out.println("access_token:" + access_token);

        return AdminResult.logoutOk(null);
    }

    @PermissionCheck(permissionTypeList = {PermissionTypeTool.sys_mgt})
    @ApiOperation(value = "查询用户信息")
    @GetMapping("userlist")
    public Result layoutname(
            @PathParam("ID") String ID,
            @PathParam("name") String name,
            @PathParam("orderType") String orderType,
            @PathParam("orderValue") String orderValue,
            @PathParam("page") int page,
            @PathParam("pageSize") int pageSize
    ) {
        AdminUserInfoBo AdminuserinfoBo = new AdminUserInfoBo();
        AdminuserinfoBo.setId(ID);
        AdminuserinfoBo.setName(name);
        AdminuserinfoBo.setOrderType(orderType);
        AdminuserinfoBo.setOrderValue(orderValue);
        AdminuserinfoBo.setPage(page);
        AdminuserinfoBo.setPageSize(pageSize);
        AdminuserinfoBo.setStartPage((page - 1) * pageSize);
//        Result res = adminuserinfoservice.getUserinfoList(userinfoBo);
        CutPageBean<AdminUserPo> cutPageBean = adminuserinfoservice.cutPage(AdminuserinfoBo);
        return Result.succ(cutPageBean);
    }

    /**
     * 管理员重置密码
     *
     * @param map id和新密码
     * @return 修改结果
     */
    @PermissionCheck(permissionTypeList = {PermissionTypeTool.sys_mgt})
    @ApiOperation(value = "修改密码")
    @PostMapping("resetPwd")
    @ResponseBody
    public Result resetPwd(
            @RequestBody HashMap<String, String> map,
            HttpServletRequest request
    ) throws NoSuchFieldException, IllegalAccessException {
        String id = map.get("id");
        String pwd = map.get("pwd");
        pwd = "123456";
        Result res = adminuserinfoservice.resetPwd(id, pwd);
        if (res.getCode() == 200) {
            Boolean insertRes = monitorService.record(request, new MonitorTypeTool().getResetPwd(), id);
        }
        return res;
    }


    /**
     * 用户首次登陆后需要修改密码,完成后,如正常登陆一样返回token
     *
     * @param map 键值对
     * @return Result token
     */
    @ApiOperation(value = "用户首次登陆修改密码")
    @PostMapping("initPwd")
    @ResponseBody
    public Result initPwd(
            @RequestBody HashMap<String, String> map
    ) {
        String id = map.get("id");
        String pwd = map.get("pwd");
        String newPwd = map.get("newPwd");
        String newPwdConfirm = map.get("newPwdConfirm");
        Result res = adminuserinfoservice.initPwd(id, pwd, newPwd, newPwdConfirm);
        return res;
    }

    @PermissionCheck(permissionTypeList = {PermissionTypeTool.sys_mute})
    @ApiOperation(value = "禁言")
    @PostMapping("mute")
    @ResponseBody
    public Result mute(
            @RequestBody HashMap<String, String> map,
            HttpServletRequest request
    ) throws NoSuchFieldException, IllegalAccessException {
        String id = map.get("id");
        AdminUserInfoBo adminuserinfoBo = new AdminUserInfoBo();
        adminuserinfoBo.setId(id);
        adminuserinfoBo.setMuteFlag("true");
        Result res = adminuserinfoservice.mute(adminuserinfoBo);
        if (res.getCode() == 200) {
            Boolean insertRes = monitorService.record(request, new MonitorTypeTool().getMute(), id);
        }
        return res;
    }

    @PermissionCheck(permissionTypeList = {PermissionTypeTool.sys_unMute})
    @ApiOperation(value = "解除禁言")
    @PostMapping("unmute")
    @ResponseBody
    public Result unmute(
            @RequestBody HashMap<String, String> map,
            HttpServletRequest request
    ) throws NoSuchFieldException, IllegalAccessException {
        String id = map.get("id");
        AdminUserInfoBo adminuserinfoBo = new AdminUserInfoBo();
        adminuserinfoBo.setId(id);
        adminuserinfoBo.setMuteFlag("false");
        Result res = adminuserinfoservice.mute(adminuserinfoBo);
        if (res.getCode() == 200) {
            Boolean insertRes = monitorService.record(request, new MonitorTypeTool().getUnmute(), id);
        }
        return res;
    }

//    @PermissionCheck(permissionTypeList  ={PermissionTypeTool.mute})
//    @ApiOperation(value = "禁言")
//    @PostMapping("mute")
//    @ResponseBody
//    public Result mute(
//            @RequestBody HashMap<String, String> map
//    ) {
//        String id = map.get("id");
//        String newState = map.get("newState");
//
//        AdminUserInfoBo adminuserinfoBo = new AdminUserInfoBo();
//        adminuserinfoBo.setId(id);
//        adminuserinfoBo.setMuteFlag(newState);
//        Result res = adminuserinfoservice.mute(adminuserinfoBo);
//        return res;
//    }

    @ApiOperation(value = "查询用户信息")
    @GetMapping("basicInfo")
    public Result basicInfo(
            @PathParam("token") String token
    ) {
        ArrayList<String> allDptsName = new ArrayList<String>();
        String userid = checkTokenReturnID(token);
        AdminUserInfoBo user = adminuserinfoservice.basicInfo(userid);
        List<AdminDepartmentPo> allDpts = admindepartmentservice.findAllDept();
        for (String depid : user.getDepartmentid().split(";")) {
            for (AdminDepartmentPo po : allDpts) {
                if (depid.equals(po.getDepartmentCode())) {
                    allDptsName.add(po.getDepartmentName());
                }
            }
        }
        user.setShowDepartment(String.join(";", allDptsName));

        return Result.succ(user);
    }

    @ApiOperation(value = "获取前端init.josn页面布局")
    @GetMapping("initJson")
    public Map<String, Object> initJson(
            HttpServletRequest request, @RequestParam("userid") String userid
    ) throws IllegalAccessException, IntrospectionException, InvocationTargetException {

        List<String> permissionGroupIDList = adminuserinfoservice.getAllFunctionPermissionGroupIdsOfUser(userid);

        String SysManage = PermissionTypeTool.front_SysManageGroupId;
        String businessManage = PermissionTypeTool.front_businessManageGroupId;
        String audit = PermissionTypeTool.front_auditGroupId;
        String jsonStr = "";
        System.out.println(userid);
        //系统+审计+非业务
        if (permissionGroupIDList.contains(SysManage) && permissionGroupIDList.contains(audit) && !permissionGroupIDList.contains(businessManage)) {
            jsonStr = FileUtil.readJsonFile("initjson/sys_shenji.json");
            System.out.println("系统+审计+非业务");
        }
        //业务+审计+非系统
        else if (permissionGroupIDList.contains(businessManage) && permissionGroupIDList.contains(audit) && !permissionGroupIDList.contains(SysManage)) {
            jsonStr = FileUtil.readJsonFile("initjson/yewu_shenji.json");
            System.out.println("业务+审计+非系统");
        }
        //系统+业务+非审计
        else if (permissionGroupIDList.contains(SysManage) && permissionGroupIDList.contains(businessManage) && !permissionGroupIDList.contains(audit)) {
            jsonStr = FileUtil.readJsonFile("initjson/sys_yewu.json");
            System.out.println("系统+业务+非审计");
        }
        //系统+非业务+非审计
        else if (permissionGroupIDList.contains(SysManage) && !permissionGroupIDList.contains(businessManage) && !permissionGroupIDList.contains(audit)) {
            jsonStr = FileUtil.readJsonFile("initjson/sys.json");
            System.out.println("系统+非业务+非审计");
        }
        //业务+非系统+非审计
        else if (permissionGroupIDList.contains(businessManage) && !permissionGroupIDList.contains(SysManage) && !permissionGroupIDList.contains(audit)) {
            jsonStr = FileUtil.readJsonFile("initjson/yewu.json");
            System.out.println("业务+非系统+非审计");
        }
        //审计+非系统+非业务
        else if (permissionGroupIDList.contains(audit) && !permissionGroupIDList.contains(SysManage) && !permissionGroupIDList.contains(businessManage)) {
            jsonStr = FileUtil.readJsonFile("initjson/shenji.json");
            System.out.println("审计+非系统+非业务");
        }
        //审计+系统+业务
        else if (permissionGroupIDList.contains(SysManage) && permissionGroupIDList.contains(businessManage) && permissionGroupIDList.contains(audit)) {
            jsonStr = FileUtil.readJsonFile("initjson/originData.json");
            System.out.println("审计+系统+业务");
        }
        //不属于任何权限组
        else {
            jsonStr = "{}";
            System.out.println("不属于任何权限组");
        }
//        String jsonStr = FileUtil.readJsonFile("initjson/originData.json");

//        String jsonStr = FileUtil.readJsonFile("initjson/sys.json");
//        String jsonStr = FileUtil.readJsonFile("initjson/yewu.json");
//        String jsonStr = FileUtil.readJsonFile("initjson/shenji.json");
//        String jsonStr = FileUtil.readJsonFile("initjson/sys_shenji.json");
//        String jsonStr = FileUtil.readJsonFile("initjson/yewu_shenji.json");
        JSONObject josnObj = (JSONObject) JSON.parse(jsonStr);
        Map res = CommonConvertUtils.convertBeanToMap(josnObj);
        Map res2 = (Map) res.get("innerMap");
        return res2;
    }

    @PermissionCheck(permissionTypeList = {PermissionTypeTool.sys_mgt})
    @ApiOperation(value = "手动新建/编辑用户接口")
    @PostMapping("addUser")
    @ResponseBody
    public Result addUser(
            @RequestBody HashMap<String, String> map,
            HttpServletRequest request
    ) throws NoSuchFieldException, IllegalAccessException {
        String id = map.get("id");
        String name = map.get("name");
        String state = map.get("state");
        String phone = map.get("phone");
        String email = map.get("email");
        String showDepartment = map.get("showDepartment");
        String departmentid = map.get("departmentid");
        String type = map.get("type");
        String salt = RandomUtils.getRandomString(4);
        String pwd = PwdUtils.generatePwdByID_Salt("123456", salt);

        //当新建的时候，检查id是否存在
        if (type.equals("add")) {
            boolean exist = adminuserinfoservice.isUserIDExist(id);
            if (exist) {
                return Result.fail("用户工号已存在!");
            }
        }

        AdminUserPo userPo = new AdminUserPo();
        userPo.setId(id);
        userPo.setName(name);
        userPo.setState(state);
        userPo.setDepartmentid(departmentid);
        userPo.setPhone(phone);
        userPo.setEmail(email);
        userPo.setPwd(pwd);
        userPo.setSalt(salt);
        userPo.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        userPo.setLastUpdateTime(userPo.getCreateTime());
        boolean res = adminuserinfoservice.addUser(userPo, type);
        if (res) {
            if ("add".equals(type)) {
                Boolean insertRes = monitorService.record(request, new MonitorTypeTool().getAddUser(), id);
            }
            return Result.succ("成功！");
        } else {
            return Result.fail("失败！");
        }
    }

    @PostMapping("/registUser")
    @ResponseBody
    public Result registUser(@RequestBody AdminUserPo userPo) {
         Boolean result = adminuserinfoservice.isUserIDExist(userPo.getId());
         if (result){
          return  Result.fail("用戶名已存在");
         }
        String salt = RandomUtils.getRandomString(4);
        String pwd = PwdUtils.generatePwdByID_Salt(userPo.getPwd(), salt);
        userPo.setPwd(pwd);
        userPo.setSalt(salt);
        userPo.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        String type = "add";
        boolean res = adminuserinfoservice.addUser(userPo, type);
        if (res) {
            return Result.succ("注册成功！");
        } else {
            return Result.succ("注册失败！");
        }
    }


    @PostMapping("/editUser")
    @ResponseBody
    public Result editUser(@RequestBody AdminUserInfoBo userPo, HttpServletRequest httpServletRequest) {
        String oldPwd = userPo.getOldPwd();
        String userId = TokenUtils.getCurrentUserId(httpServletRequest);
         AdminUserInfoBo adminUserInfoBo =  adminuserinfoservice.getUserById(userId);
        String pwd = PwdUtils.generatePwdByID_Salt(oldPwd, adminUserInfoBo.getSalt());
        if (pwd.equals(adminUserInfoBo.getPwd())){
            String salt = RandomUtils.getRandomString(4);
            String newPwd = PwdUtils.generatePwdByID_Salt(oldPwd, salt);
            userPo.setSalt(salt);
            userPo.setPwd(newPwd);
              Boolean res  =adminuserinfoservice.updateUserInfo(userPo);
              if (res){
                  return Result.succ("修改个人信息成功");
              }else {
                  return Result.fail("修改个人信息失败");
              }
        }else {
            return Result.fail("原密码不正确");
        }

    }


    @PermissionCheck(permissionTypeList = {PermissionTypeTool.sys_mgt})
    @ApiOperation(value = "删除用户")
    @PostMapping("deleteUser")
    @ResponseBody
    public Result deleteUser(
            @RequestBody HashMap<String, String> map,
            HttpServletRequest request
    ) throws NoSuchFieldException, IllegalAccessException {
        String id = map.get("id");

        AdminUserPo userPo = new AdminUserPo();
        userPo.setId(id);

        boolean res = adminuserinfoservice.deleteUser(userPo);
        if (res) {
            Boolean insertRes = monitorService.record(request, new MonitorTypeTool().getDeleteUser(), id);
            return Result.succ("删除成功！");
        } else {
            return Result.fail("删除失败！");
        }
    }


    @ApiOperation(value = "用户修改自己的密码")
    @PostMapping("changeMyPwd")
    @ResponseBody
    public Result changeMyPwd(
            HttpServletRequest request,
            @RequestBody HashMap<String, String> map
    ) {
        String userid = TokenUtils.getCurrentUserId(request);
        String oldPwd = map.get("oldPwd");
        String newPwd = map.get("newPwd");

        AdminLoginPo adminloginpo = new AdminLoginPo();
        adminloginpo.setId(userid);
        adminloginpo.setPwd(oldPwd);
        adminloginpo.setNewpwd(newPwd);

        Result res = adminuserinfoservice.changeMyPwd(adminloginpo);
        return res;
    }

    @ApiOperation(value = "下载导入用户的模板")
    @GetMapping("getTemplate")
//    @RequestMapping(value = "getTemplate")
    public void getTemplate(HttpServletResponse resp, HttpServletRequest request) {
        String tpType = request.getParameter("tpType");
        String realPath = "";   //源文件URL
        if ("userBatchImp".equals(tpType)) {
            realPath = "static/ExcelTemplates/importUser.xlsx";
        }
        //- 准备需要下载的文件的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("/") + 1);
        //- 设置浏览器的支持下载
        try {
            resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //- 获取到下载到的文件的输入流
        InputStream in = this.getClass().getClassLoader().getResourceAsStream(realPath);
        //- 创建一个缓冲区用来写入流
        int len = 0;
        byte[] bytes = new byte[1024];
        //- 获取OutputStream对象
        ServletOutputStream outputStream = null;
        try {
            outputStream = resp.getOutputStream();//- 将FileOutputStream对象的流写入到先前创建的buffer缓冲区中,使用OutputStream对象将buffer缓冲区中的数据输出到自己的客户端中
            while ((len = in.read(bytes)) > 0) {
                outputStream.write(bytes, 0, len);
            }
            outputStream.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @ApiOperation(value = "批量导入用户时,接收excel文件的接口")
    @PostMapping("handleBatchImportUser")
    public Result handleBatchImportUser(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception {
        //步骤一: 获取文件名 AA.xlsx*********************************/
        String fileName = file.getOriginalFilename();
        //步骤二: 为文件AA.xlsx生成随机目录 4D2Gf_AA*****************/
        String dirName = RandomUtils.getRandomString(5) + "_" + fileName.substring(0, fileName.lastIndexOf("."));
        //步骤三: 拼接随机目录+文件名 xxx\4D2Gf_AA
        String dirPath = updUserExcelPath + "\\" + dirName;
        //步骤四: 拼接文件绝对路径 D:\cnki\xxx\4D2Gf_AA\AA.xlsx
        String absPath = dirPath + "\\" + fileName;
        //步骤五: 保存该文件至springboot服务器
        FileUtil.saveFile(file, dirPath, fileName);
        //步骤六: 获取当前系统中所有的用户id
        //这里注释是因为采用了REC方式,不必再手动判断工号是否存在
        //List<AdminUserPo> allUsers = adminuserinfoservice.getAllUser();
        //ArrayList<String> allUserIdList = new ArrayList<String>();
        //for (AdminUserPo userPo:allUsers){
        //    allUserIdList.add(userPo.getId());
        //}
        //步骤七: 获取当前系统中所有的部门id
        List<AdminDepartmentPo> allDpts = admindepartmentservice.findAllDept();
        ArrayList<String> allDptIdList = new ArrayList<String>();
        for (AdminDepartmentPo dptPo : allDpts) {
            allDptIdList.add(dptPo.getDepartmentCode());
        }

        //步骤八: 验证excel数据合法性
        JSONArray jsonArray = null;
        /*******************步骤八: 检测1 ：excel内容为空检测************************/
        try {
            jsonArray = excelResolve.readExcel(new File(absPath));
            if (jsonArray.size() == 0) {
                return Result.fail("excel内容为空");
            }
        } catch (Exception e) {
            return Result.fail("excel存在空列");
        }
        /*******************步骤八: 检测2 ：表头完整性检测************************/
        ArrayList<String> needHeaders = Lists.newArrayList("userid", "userName", "orgId", "mobile", "email");
        Object[] keysSet = jsonArray.getJSONObject(0).keySet().toArray();
        ArrayList<String> keysList = new ArrayList<String>();
        for (Object i : keysSet) {
            keysList.add(i.toString());
        }
        for (String i : needHeaders) {
            if (!keysList.contains(i)) {
                return Result.fail("excel缺少必要表头:" + i);
            }
        }
        /*******************步骤八: 检测3 ：单行数据检测************************/
        for (int i = 0; i < jsonArray.size(); i++) {
            net.sf.json.JSONObject lineObject = jsonArray.getJSONObject(i);
            String userid = lineObject.get("userid").toString();
            String userName = lineObject.get("userName").toString();
            String orgId = lineObject.get("orgId").toString();
            /*******步骤八: 检测3 ：单行数据检测 1:每一行中部分字段是必填************/
            if ("".equals(userid) || "".equals(userName) || "".equals(orgId)) {
                return Result.fail(String.format("excel第%d行有空值", i + 1));
            }
            /*******步骤八: 检测3 ：单行数据检测 2:用户的部门id不能为0************/
            if ("0".equals(orgId)) {
                return Result.fail(String.format("部门编号不能为0,第%s行", i + 1));
            }
            /*******步骤八: 检测3 ：单行数据检测 3:用户id必须不存在************/
            //这里注释是因为采用了REC方式,允许id存在,存在的含义是:修改
            //if (allUserIdList.contains(userid)){
            //    return Result.fail(String.format("用户编号已存在，不可新建！第%s行",i+1));
            //}
            /**步骤八: 检测3 ：单行数据检测 4:用户部门id必须存在(可能有多个用;隔开的部门)**/
            for (String singleOrgId : orgId.split(";")) {
                if (!allDptIdList.contains(singleOrgId)) {
                    return Result.fail(String.format("部门编号不存在，不可新建！第%s行:%s", i + 1, singleOrgId));
                }
            }
        }
        //步骤九: 验证通过,将excel数据写入数据库(REC方式)
        boolean res = adminuserinfoservice.writeExcelData(jsonArray);

        Boolean insertRes = monitorService.record(request, new MonitorTypeTool().getAddUserBatch(), dirPath);

        return Result.succ(res);
    }

}